A look at the latest Jedlovec House eletricity usage and solar production from PPL and Enphase.
Load packages
library(tidyverse)
library(lubridate)
library(hms)
library(readxl)
Load PPL data
Transform PPL Data
hourly_ppl_pivot <- ppl_15mins %>%
rename(date = Date) %>%
pivot_longer(!c("Account Number", "Meter Number", date, "Read Type", Min, Max, Total), names_to = "time", values_to = "kWh")
rename(ppl_15mins, date = Date)
hourly_ppl_pivot <- hourly_ppl_pivot %>%
mutate(time = parse_time(time, '%H:%M %p'), month = month(date, label=TRUE), year = year(date), yday = yday(date), wday = wday(date, label=TRUE))
(hourly_ppl_net <- hourly_ppl_pivot %>%
filter(`Read Type` == "kWh Net"))
Load Enphase data
import <- read_csv("enphase_history_230701.csv")
Rows: 42432 Columns: 2── Column specification ────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Date/Time
dbl (1): Energy Produced (Wh)
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
update <- read_csv("hourly_generation_230625_240510.csv")
Rows: 30816 Columns: 2── Column specification ────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Date/Time
dbl (1): Energy Produced (Wh)
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
update <- update %>%
mutate(`Date/Time` = as.POSIXct(`Date/Time`,format="%m/%d/%Y %H:%M",tz=Sys.timezone())) %>%
filter(`Date/Time` >= as.POSIXct('07/01/2023 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) )
import <- import %>%
mutate(`Date/Time` = as.POSIXct(`Date/Time`,format="%m/%d/%Y %H:%M",tz=Sys.timezone()))
full_hist <- rbind(import,update)
full_hist %>% arrange(desc(`Date/Time`))
(hourly_production <- full_hist %>%
rename(datetime = `Date/Time`, energy_produced_Wh = `Energy Produced (Wh)`) %>%
mutate(datetime = as.POSIXct(datetime,format="%m/%d/%Y %H:%M",tz=Sys.timezone())) %>%
mutate(date = date(datetime), time = as.hms(format(datetime, format = "%H:%M:%S")), month = month(datetime, label=TRUE), year = year(datetime), day = day(datetime), yday = yday(datetime), monthday = format(datetime, "%m-%d"), wday = wday(datetime, label=TRUE), equinox_day = (yday + 10) %% 365, equinox_group = floor((equinox_day+15)/30)*30)
)
NA
Spot-check Enphase Should see lifetime production by day and by hour
ggplot(hourly_production, aes(datetime, energy_produced_Wh)) +
geom_point()
ggplot(hourly_production, aes(time, energy_produced_Wh)) +
theme(axis.text.x = element_text(angle = 90)) +
geom_point()
Net + Produced = Consumed
Calculate production for first year of solar panels, second year, etc.
hourly_electricity <- hourly_electricity %>%
mutate(solar_year = factor(case_when(
datetime < as.POSIXct('04/16/2022 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) ~ 0,
datetime >= as.POSIXct('04/16/2022 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) &
datetime < as.POSIXct('04/16/2023 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) ~ 1,
datetime >= as.POSIXct('04/16/2023 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) &
datetime < as.POSIXct('04/16/2024 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) ~ 2,
TRUE ~ 3)
)) %>%
mutate(yday = yday(date))
hourly_electricity %>%
group_by(solar_year) %>%
summarize(net_kWh = sum(net_kWh), produced_kWh = sum(produced_kWh), consumed_kWh = sum(consumed_kWh))
NA
Interesting! Produced kWh went down by 5%, but consumed kWh went down by 10% despite the fact that we got an electric car! Let’s explore that further.
daily_electricity <- hourly_electricity %>%
group_by(solar_year, yday) %>%
summarize(net_kWh = sum(net_kWh), produced_kWh = sum(produced_kWh), consumed_kWh = sum(consumed_kWh))
`summarise()` has grouped output by 'solar_year'. You can override using the `.groups` argument.
ggplot(daily_electricity, aes(yday, consumed_kWh, group=solar_year, color=solar_year)) +
geom_point() +
geom_smooth(span=0.3) +
scale_x_continuous(breaks = c(1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335), labels = month.abb) +
theme(axis.text.x = element_text(angle = 90))
Look how our electricity consumption got much less predictable, more uneven, after we purchased an EV and installed a level 2 charger in late January/early February 2023!
We probably need to filter out the EV charging and compare that separately.
hourly_electricity %>% summarize(min_date = min(date), max_date = max(date))
electricity_by_time <- hourly_electricity %>%
filter(solar_year == 1 | solar_year == 2) %>%
#filter(date <= as.POSIXct('12/31/2022 00:00',format="%m/%d/%Y %H:%M",tz=Sys.timezone()) ) %>%
group_by(time, solar_year) %>%
summarize(produced_kWh = mean(produced_kWh), consumed_kWh = mean(consumed_kWh), net_kWh = mean(net_kWh)) %>%
arrange(time)
`summarise()` has grouped output by 'time'. You can override using the `.groups` argument.
electricity_by_time
ggplot(electricity_by_time, aes(x=time, y=consumed_kWh, group=solar_year, color=solar_year)) +
geom_point()
#labs(colour="",x="Time of Day",y="Electricity Consumption (kWh)")+
#scale_color_manual(values = c("red","black","green")) +
#ggtitle("Home Electricity in 15-Minute Intervals (Since April 15, 2022)")
Wow, look how much less was used during the day in year 2!!! Like a 50% reduction!
Is this due to milder weather?
Let’s look at it by month:
#electricity_by_month <-
hourly_electricity %>%
mutate(month = month(date)) %>%
group_by(solar_year, month) %>%
summarize(consumed_kWh = mean(consumed_kWh)) %>%
arrange(month, solar_year) %>%
pivot_wider(names_from = month, values_from = consumed_kWh) %>%
arrange(solar_year)
`summarise()` has grouped output by 'solar_year'. You can override using the `.groups` argument.
#Look at limited window during day (no EV charging)
# hourly_electricity %>%
# filter(time == '12:00:00') %>%
# #filter(time > as.POSIXct('04:00:00',format="%H:%M:$s",tz=Sys.timezone()) ) %>% #& time < as.POSIXct('18:00',format="%H:%M",tz=Sys.timezone())) %>%
# mutate(month = month(date)) %>%
# group_by(solar_year, month) %>%
# summarize(consumed_kWh = mean(consumed_kWh)) %>%
# arrange(month, solar_year) %>%
# pivot_wider(names_from = month, values_from = consumed_kWh) %>%
# arrange(solar_year)
Look at specific months
electricity_by_month_time <- hourly_electricity %>%
mutate(month = as_factor(month(date))) %>%
filter(solar_year == 1 | solar_year == 2) %>%
filter(month == 10) %>%
group_by(solar_year, month, time) %>%
summarize(produced_kWh = mean(produced_kWh), consumed_kWh = mean(consumed_kWh), net_kWh = mean(net_kWh)) %>%
arrange(solar_year, month, time)
`summarise()` has grouped output by 'solar_year', 'month'. You can override using the `.groups` argument.
ggplot(electricity_by_month_time, aes(time, consumed_kWh, group=solar_year, color=solar_year)) +
#facet_grid(rows = vars(month)) +
geom_point(size=0.5) +
ggtitle("Home Electricity in 15-Minute Intervals") +
ylab("Net Electricity Consumption (kWh)")
Example day with EV charging
sample_day <- hourly_electricity %>%
filter(solar_year == 1 | solar_year == 2) %>%
filter(yday == 157) %>%
group_by(date, solar_year, yday, time) %>%
summarize(produced_kWh = mean(produced_kWh), consumed_kWh = mean(consumed_kWh), net_kWh = mean(net_kWh)) %>%
arrange(date, solar_year, yday, time)
`summarise()` has grouped output by 'date', 'solar_year', 'yday'. You can override using the `.groups` argument.
ggplot(sample_day, aes(time, consumed_kWh, group=solar_year, color=solar_year)) +
#facet_grid(rows = vars(month)) +
geom_point(size=0.5) +
ggtitle("Home Electricity in 15-Minute Intervals") +
ylab("Electricity Consumption (kWh)")
Ok, let’s detect and remove EV charging sessions.
bcp
$x
[1] 2.38157896 2.49495792 2.35871228 2.67047501 2.71991881 2.55883013 2.33772138 2.91051260
[9] 2.19237889 2.74960191 1.75213595 -0.01838713 0.30820336 0.39897059 0.28664757 0.30603608
[17] 0.35919098 0.16767281 0.21823037 0.43193225 0.33928205 0.39538327 0.39027328 0.25107071
[25] 0.21501386 0.12773723 0.07036768 0.02051450 0.03319477 0.18027518 0.33188973 0.38038835
[33] 0.13785630 0.42017572 0.22867892 0.24044121 0.23030774 0.28537113 0.51695711 0.29266042
[41] -0.06083516 0.06660989 0.31487811 0.14387669 0.39981560 0.30094562 0.09083242 0.35589074
[49] 0.04101847 0.13585666 0.01485267 0.42753704 0.27042197 0.09039031 0.52307131 0.18050086
[57] 0.28360934 0.71996580 0.20057504 0.35998894 0.47077430 0.21099498 0.32290440 0.14337854
[65] 0.29055250 -0.07771297 0.31868915 0.43214999 0.21821496 0.20267917 0.22137171 0.19991720
[73] 0.15276440 0.48992731 0.27547768 0.13486293 0.19747790 0.15852249 0.03325269 0.15447847
[81] -0.02821081 0.06667815 -0.20491370 0.13184547 0.08786327 0.25226203 0.02591429 0.24308958
[89] 0.37162490 0.15715362 0.12179673 -0.14603414 0.20990544 0.38083345 0.02071311 0.26131271
[97] 0.07817865
$max_p
[,1] [,2] [,3]
[1,] 0.9580194 0 0
[2,] 0.9364674 0 1
[3,] 0.9291162 0 2
[4,] 0.9265527 0 3
[5,] 0.9265851 0 4
[6,] 0.9267314 0 5
[7,] 0.9319284 0 6
[8,] 0.9302070 0 7
[9,] 0.9382416 0 8
[10,] 0.9188706 0 9
[11,] 0.4892223 0 10
[12,] 0.6201123 11 0
[13,] 0.8095788 11 1
[14,] 0.7979013 11 2
[15,] 0.7929583 11 3
[16,] 0.7921342 11 4
[17,] 0.7971379 11 5
[18,] 0.8047930 11 6
[19,] 0.8080573 11 7
[20,] 0.8163079 11 8
[21,] 0.8221754 11 9
[22,] 0.8283082 11 10
[23,] 0.8366701 11 11
[24,] 0.8438057 11 12
[25,] 0.8481012 11 13
[26,] 0.8504027 11 14
[27,] 0.8507848 11 15
[28,] 0.8547635 11 16
[29,] 0.8662926 11 17
[30,] 0.8722353 11 18
[31,] 0.8742465 11 19
[32,] 0.8783681 11 20
[33,] 0.8776178 11 21
[34,] 0.8835105 11 22
[35,] 0.8870574 11 23
[36,] 0.8896860 11 24
[37,] 0.8914833 11 25
[38,] 0.8796208 11 26
[39,] 0.8882480 11 27
[40,] 0.8727340 11 28
[41,] 0.8822929 11 29
[42,] 0.8917103 11 30
[43,] 0.8947029 11 31
[44,] 0.8936474 11 32
[45,] 0.8971827 11 33
[46,] 0.8957289 11 34
[47,] 0.8977034 11 35
[48,] 0.8935607 11 36
[49,] 0.8989002 11 37
[50,] 0.8934545 11 38
[51,] 0.8949324 11 39
[52,] 0.9020641 11 40
[53,] 0.9011736 11 41
[54,] 0.8869148 11 42
[55,] 0.8999069 11 43
[56,] 0.9039034 11 44
[57,] 0.8233297 11 45
[58,] 0.8803324 11 46
[59,] 0.8933737 11 47
[60,] 0.8894446 11 48
[61,] 0.8983125 11 49
[62,] 0.9004938 11 50
[63,] 0.9002783 11 51
[64,] 0.9025502 11 52
[65,] 0.8758334 11 53
[66,] 0.8969529 11 54
[67,] 0.8960692 11 55
[68,] 0.9020904 11 56
[69,] 0.9038043 11 57
[70,] 0.9048967 11 58
[71,] 0.9052346 11 59
[72,] 0.9045400 11 60
[73,] 0.8937625 11 61
[74,] 0.9026525 11 62
[75,] 0.9025963 11 63
[76,] 0.9050601 11 64
[77,] 0.9050209 11 65
[78,] 0.8969872 11 66
[79,] 0.9041006 11 67
[80,] 0.8884811 11 68
[81,] 0.8971434 11 69
[82,] 0.8047584 11 70
[83,] 0.8785588 11 71
[84,] 0.8964911 11 72
[85,] 0.9082148 11 73
[86,] 0.9023057 11 74
[87,] 0.9110744 11 75
[88,] 0.9091609 11 76
[89,] 0.9118557 11 77
[90,] 0.9116388 11 78
[91,] 0.8629416 11 79
[92,] 0.9032366 11 80
[93,] 0.9069030 11 81
[94,] 0.9035397 11 82
[95,] 0.9127871 11 83
[96,] 0.9111167 11 84
[97,] 0.0000000 0 0
$parameters
theta alpha beta th_cp
0.9 1.0 1.0 0.5
$series_length
[1] 97
$result
NULL
attr(,"class")
[1] "BayesCP"
plot(summary(bcp))
[1] "Change points"
[1] "Segments"
begin end mean SD LL of CI UL of CI
[1,] 1 11 2.5354545 0.31740711 2.3780390 2.6928701
[2,] 12 96 0.1314471 0.09968958 0.1136615 0.1492326